/**
 * @file /src/main_window.cpp
 *
 * @brief Implementation for the qt gui.
 *
 * @date February 2011
 **/
/*****************************************************************************
** Includes
*****************************************************************************/

#include <QtGui>
#include <QMessageBox>
#include <iostream>
#include "../include/car_sim/main_window.hpp"

/*****************************************************************************
** Namespaces
*****************************************************************************/

namespace car_sim {

using namespace Qt;

/*****************************************************************************
** Implementation [MainWindow]
*****************************************************************************/

MainWindow::MainWindow(int argc, char** argv, QWidget *parent)
	: QMainWindow(parent)
	, qnode(argc,argv)
{
	ui.setupUi(this); // Calling this incidentally connects all ui's triggers to on_...() callbacks in this class.
    QObject::connect(ui.actionAbout_Qt, SIGNAL(triggered(bool)), qApp, SLOT(aboutQt())); // qApp is a global variable for the application

    ReadSettings();
	setWindowIcon(QIcon(":/images/icon.png"));
	ui.tab_manager->setCurrentIndex(0); // ensure the first tab is showing - qt-designer should have this already hardwired, but often loses it (settings?).
    QObject::connect(&qnode, SIGNAL(rosShutdown()), this, SLOT(close()));

	/*********************
	** Logging
	**********************/
	ui.view_logging->setModel(qnode.loggingModel());
    QObject::connect(&qnode, SIGNAL(loggingUpdated()), this, SLOT(updateLoggingView()));

    /*********************
    ** Auto Start
    **********************/
    if ( ui.checkbox_remember_settings->isChecked() ) {
        on_button_connect_clicked(true);
    }
    /******************************************************************************************************************************************************
     * My Code Below ***************************************************************************************************************************************
     * ******************************************************************************************************************************************************/

    //显示油门和转向的步长
    ui.label_acc_val->setText((QString::number(ui.horizontalSlider_acc->value())));
    ui.label_turning_val->setText((QString::number(ui.horizontalSlider_turning->value())));

    //显示当前油门量和转向量
    ui.progressBar_acc->setValue((int)this->qnode.get_x() * 10 + 100);
    ui.progressBar_turning->setValue((int)this->qnode.get_z() * 100 + 50);

    //将加速度与转弯速度的值传入qnode中
    this->qnode.set_acc(ui.horizontalSlider_acc->value());
    this->qnode.set_turn_acc(ui.horizontalSlider_turning->value());
    //将progressBar传给qnode更新
    this->qnode.set_progressBar_acc(ui.progressBar_acc);
    this->qnode.set_progressBar_turning(ui.progressBar_turning);

    connect(ui.horizontalSlider_acc, SIGNAL(valueChanged(int)), this, SLOT(on_horizontalSlider_acc_valueChanged(int)));
    connect(ui.horizontalSlider_turning, SIGNAL(valueChanged(int)), this, SLOT(on_horizontalSlider_turning_valueChanged(int)));
    connect(ui.pushButton_I, SIGNAL(clicked()), this, SLOT(slot_pushbtn_click()));
    connect(ui.pushButton_K, SIGNAL(clicked()), this, SLOT(slot_pushbtn_click()));
    connect(ui.pushButton_J, SIGNAL(clicked()), this, SLOT(slot_pushbtn_click()));
    connect(ui.pushButton_L, SIGNAL(clicked()), this, SLOT(slot_pushbtn_click()));

    //仪表盘控件
    speed_x_dashBoard = new CCtrlDashBoard(ui.widget_speed_x);
    speed_y_dashBoard = new CCtrlDashBoard(ui.widget_speed_y);
    speed_x_dashBoard->setGeometry(ui.widget_speed_x->rect());
    speed_y_dashBoard->setGeometry(ui.widget_speed_y->rect());
    speed_x_dashBoard->setValue(0);
    speed_y_dashBoard->setValue(0);

    connect(&qnode, SIGNAL(speed_vel(float, float)), this, SLOT(slot_update_dashboard(float, float)));

    /******************************************************************************************************************************************************
     * My Code Above ---------------------------------------------------------------------------------------------------------------------------------------
     * ******************************************************************************************************************************************************/

}

MainWindow::~MainWindow() {}

/*****************************************************************************
** Implementation [Slots]
*****************************************************************************/

void MainWindow::showNoMasterMessage() {
	QMessageBox msgBox;
	msgBox.setText("Couldn't find the ros master.");
	msgBox.exec();
    close();
}

/*
 * These triggers whenever the button is clicked, regardless of whether it
 * is already checked or not.
 */

void MainWindow::on_button_connect_clicked(bool check ) {
	if ( ui.checkbox_use_environment->isChecked() ) {
		if ( !qnode.init() ) {
			showNoMasterMessage();
		} else {
			ui.button_connect->setEnabled(false);
		}
	} else {
		if ( ! qnode.init(ui.line_edit_master->text().toStdString(),
				   ui.line_edit_host->text().toStdString()) ) {
			showNoMasterMessage();
		} else {
			ui.button_connect->setEnabled(false);
			ui.line_edit_master->setReadOnly(true);
			ui.line_edit_host->setReadOnly(true);
			ui.line_edit_topic->setReadOnly(true);
		}
	}
}


void MainWindow::on_checkbox_use_environment_stateChanged(int state) {
	bool enabled;
	if ( state == 0 ) {
		enabled = true;
	} else {
		enabled = false;
	}
	ui.line_edit_master->setEnabled(enabled);
	ui.line_edit_host->setEnabled(enabled);
	//ui.line_edit_topic->setEnabled(enabled);
}

/*****************************************************************************
** Implemenation [Slots][manually connected]
*****************************************************************************/

/**
 * This function is signalled by the underlying model. When the model changes,
 * this will drop the cursor down to the last line in the QListview to ensure
 * the user can always see the latest log message.
 */
void MainWindow::updateLoggingView() {
        ui.view_logging->scrollToBottom();
}

/*****************************************************************************
** Implementation [Menu]
*****************************************************************************/

void MainWindow::on_actionAbout_triggered() {
    QMessageBox::about(this, tr("About ..."),tr("<h2>PACKAGE_NAME Test Program 0.10</h2><p>Copyright Yujin Robot</p><p>This package needs an about description.</p>"));
}

/*****************************************************************************
** Implementation [Configuration]
*****************************************************************************/

void MainWindow::ReadSettings() {
    QSettings settings("Qt-Ros Package", "car_sim");
    restoreGeometry(settings.value("geometry").toByteArray());
    restoreState(settings.value("windowState").toByteArray());
    QString master_url = settings.value("master_url",QString("http://192.168.1.2:11311/")).toString();
    QString host_url = settings.value("host_url", QString("192.168.1.3")).toString();
    //QString topic_name = settings.value("topic_name", QString("/chatter")).toString();
    ui.line_edit_master->setText(master_url);
    ui.line_edit_host->setText(host_url);
    //ui.line_edit_topic->setText(topic_name);
    bool remember = settings.value("remember_settings", false).toBool();
    ui.checkbox_remember_settings->setChecked(remember);
    bool checked = settings.value("use_environment_variables", false).toBool();
    ui.checkbox_use_environment->setChecked(checked);
    if ( checked ) {
    	ui.line_edit_master->setEnabled(false);
    	ui.line_edit_host->setEnabled(false);
    	//ui.line_edit_topic->setEnabled(false);
    }
}

void MainWindow::WriteSettings() {
    QSettings settings("Qt-Ros Package", "car_sim");
    settings.setValue("master_url",ui.line_edit_master->text());
    settings.setValue("host_url",ui.line_edit_host->text());
    //settings.setValue("topic_name",ui.line_edit_topic->text());
    settings.setValue("use_environment_variables",QVariant(ui.checkbox_use_environment->isChecked()));
    settings.setValue("geometry", saveGeometry());
    settings.setValue("windowState", saveState());
    settings.setValue("remember_settings",QVariant(ui.checkbox_remember_settings->isChecked()));

}

void MainWindow::closeEvent(QCloseEvent *event)
{
	WriteSettings();
	QMainWindow::closeEvent(event);
}

}  // namespace car_sim

/******************************************************************************************************************************************************
 * My Code Below ***************************************************************************************************************************************
 * ******************************************************************************************************************************************************/

void car_sim::MainWindow::on_horizontalSlider_acc_valueChanged(int value)
{
    ui.label_acc_val->setText((QString::number(value)));
    this->qnode.set_acc(ui.horizontalSlider_acc->value());
}

void car_sim::MainWindow::on_horizontalSlider_turning_valueChanged(int value)
{
    ui.label_turning_val->setText((QString::number(value)));
    this->qnode.set_turn_acc(ui.horizontalSlider_turning->value());
}

void car_sim::MainWindow::slot_pushbtn_click()
{
    QPushButton* btn = qobject_cast<QPushButton*>(sender());
    char k = btn->text().toStdString()[0];
    bool use_keyboard = ui.checkBox_use_keyboard->isChecked();
    float acc = ui.label_acc_val->text().toFloat() * 0.1;
    float turning = ui.label_turning_val->text().toFloat() * 0.01;
    if(use_keyboard){
        switch (k) {
            case 'I':
                qnode.set_cmd_vel('I', acc, turning);
                break;
            case 'K':
                qnode.set_cmd_vel('K', acc, turning);
                break;
            case 'J':
                qnode.set_cmd_vel('J', acc, turning);
                break;
            case 'L':
                qnode.set_cmd_vel('L', acc, turning);
                break;
        }
    }
}

void car_sim::MainWindow::slot_update_dashboard(float x, float y){
    speed_x_dashBoard->setValue(x * 100);
    speed_y_dashBoard->setValue(y * 100);
}

//键盘按下事件
void car_sim::MainWindow::keyPressEvent(QKeyEvent * event)
{
    switch (event->key())
    {
        case Qt::Key_W:
            //this->qnode.sent_cmd_vel('W');
            if(!event->isAutoRepeat()){
                this->qnode.keyboard_press['W']=true;
            }
            break;
        case Qt::Key_S:
            //this->qnode.sent_cmd_vel('S');
            if(!event->isAutoRepeat()){
                this->qnode.keyboard_press['S']=true;
            }
            break;
        case Qt::Key_A:
            //this->qnode.sent_cmd_vel('A');
            if(!event->isAutoRepeat()){
                this->qnode.keyboard_press['A']=true;
            }
            break;
        case Qt::Key_D:
            //this->qnode.sent_cmd_vel('D');
            if(!event->isAutoRepeat()){
                this->qnode.keyboard_press['D']=true;
            }
            break;
    }
}

//键盘松开事件
void car_sim::MainWindow::keyReleaseEvent(QKeyEvent *event)
{
    switch (event->key())
    {
        case Qt::Key_W:
            if(!event->isAutoRepeat()){
                this->qnode.keyboard_press['W']=false;
            }
        break;
        case Qt::Key_S:
            if(!event->isAutoRepeat()){
                this->qnode.keyboard_press['S']=false;
            }
        break;
        case Qt::Key_A:
            if(!event->isAutoRepeat()){
                this->qnode.keyboard_press['A']=false;
            }
        break;
        case Qt::Key_D:
            if(!event->isAutoRepeat()){
                this->qnode.keyboard_press['D']=false;
            }
        break;
    }
}

/******************************************************************************************************************************************************
 * My Code Above ---------------------------------------------------------------------------------------------------------------------------------------
 * ******************************************************************************************************************************************************/
